package proxy

import (
	"db-sharding/mysql"
	"db-sharding/sqlparser"
	"db-sharding/system/log4go"
	"db-sharding/system/try"
	"fmt"
	"github.com/pingcap/parser/ast"
	"strings"
)

func (c *Conn) handleQueryNew(sql string) (err error) {
	defer try.CatchException(nil)

	log4go.Debug("网络日志", "sql追踪", sql)

	sql = strings.TrimRight(sql, ";")
	stmts, _, err := SqlParse.Parse(sql, c.charset, mysql.Collations[c.collation])
	if err != nil {
		log4go.Error("解析失败，进行重试", err.Error(), sql)
		return c.handleQueryNewRewrite(sql)
	}

	for _, stmt := range stmts {
		switch v := stmt.(type) {
		case *ast.SelectStmt:
			log4go.Debug("查", sql)
			return c.handleSelectNew(sql)
		case *ast.InsertStmt:
			log4go.Debug("增", sql)
			actual, lotCode := sqlparser.RewriteInsertStmt(sql)
			return c.handleExecInert(actual, lotCode, nil)
		case *ast.UpdateStmt:
			log4go.Debug("改", sql)
			actual, lotCode := sqlparser.RewriteUpdateStmt(sql)
			return c.handleExecInert(actual, lotCode, nil)
		case *ast.DeleteStmt:
			log4go.Debug("删", sql)
			actual, lotCode := sqlparser.RewriteDeleteStmt(sql)
			return c.handleExecInert(actual, lotCode, nil)
		case *ast.SetStmt:
			//log4go.Debug("设置预编辑SetStmt")
			return c.handleSetNew(v)
		case *ast.BeginStmt:
			//log4go.Info("开启事务")
			return c.handleBegin()
		case *ast.CommitStmt:
			//log4go.Info("提交事务")
			return c.handleCommit()
		case *ast.RollbackStmt:
			//log4go.Info("回滚事务")
			return c.handleRollback()
		case *ast.ShowStmt:
			//log4go.Info("显示预编辑 ShowStmt")
			return c.handleShowNew(sql)
		case *ast.AdminStmt:
			log4go.Warn("管理")
		default:
			log4go.Warn("还没实现的语句", v)
		}
	}
	log4go.Warn("尚未实现：", sql)

	return c.writeOK(nil)
}

func (c *Conn) handleQueryNewRewrite(sql string) (err error) {
	defer try.CatchException(nil)

	log4go.Debug("网络日志", "sql追踪", sql)

	var stmt sqlparser.Statement
	stmt, err = sqlparser.Parse(sql)
	if err != nil {
		log4go.Error("解析失败", err.Error(), sql)
		return fmt.Errorf(`parse sql "%s" error`, sql)
	}

	switch v := stmt.(type) {
	case *sqlparser.Select:
		log4go.Debug("查", sql)
		return c.handleSelectNew(sql)
	case *sqlparser.Insert:
		log4go.Debug("增", sql)
		actual, lotCode := sqlparser.RewriteInsertStmt(sql)
		return c.handleExecInert(actual, lotCode, nil)
	case *sqlparser.Update:
		log4go.Debug("改", sql)
		actual, lotCode := sqlparser.RewriteUpdateStmt(sql)
		return c.handleExecInert(actual, lotCode, nil)
	case *sqlparser.Delete:
		log4go.Debug("删", sql)
		actual, lotCode := sqlparser.RewriteDeleteStmt(sql)
		return c.handleExecInert(actual, lotCode, nil)
	//case *sqlparser.Replace:
	//	log4go.Debug("删", sql)
	//	return c.handleExec(stmt, sql, nil)
	case *sqlparser.Set:
		return c.handleSet(v)
	case *sqlparser.Begin:
		return c.handleBegin()
	case *sqlparser.Commit:
		return c.handleCommit()
	case *sqlparser.Rollback:
		return c.handleRollback()
	case *sqlparser.SimpleSelect:
		return c.handleSimpleSelect(sql, v)
	case *sqlparser.Show:
		return c.handleShow(sql, v)
	case *sqlparser.Admin:
		return c.handleAdmin(v)
	default:
		return fmt.Errorf("statement %T not support now", stmt)
	}
}

func executeShard(sql string, c *Conn) error {
	//TODO 解析sql
	var stmt sqlparser.Statement
	stmt, err := sqlparser.Parse(sql)
	if err != nil {
		return fmt.Errorf(`parse sql "%s" error`, sql)
	}

	switch v := stmt.(type) {
	case *sqlparser.Select:
		return c.handleSelect(v, sql, nil)
	case *sqlparser.Insert:
		return c.handleExec(stmt, sql, nil)
	case *sqlparser.Update:
		return c.handleExec(stmt, sql, nil)
	case *sqlparser.Delete:
		return c.handleExec(stmt, sql, nil)
	case *sqlparser.Replace:
		return c.handleExec(stmt, sql, nil)
	case *sqlparser.Set:
		return c.handleSet(v)
	case *sqlparser.Begin:
		return c.handleBegin()
	case *sqlparser.Commit:
		return c.handleCommit()
	case *sqlparser.Rollback:
		return c.handleRollback()
	case *sqlparser.SimpleSelect:
		return c.handleSimpleSelect(sql, v)
	case *sqlparser.Show:
		return c.handleShow(sql, v)
	case *sqlparser.Admin:
		return c.handleAdmin(v)
	default:
		return fmt.Errorf("statement %T not support now", stmt)
	}
}
